package com.njzxw.fs.serverzuul.fitter;

import com.google.gson.Gson;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.http.ServletInputStreamWrapper;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;

/**
 * 权限过滤器
 */
@Component
public class MyPreAccessFilter extends BaseFilter {

    /**
     *

     pre：路由之前

     routing：路由之时

     post： 路由之后

     error：发送错误调用

     * @return
     */
    @Override
    public String filterType() {

        return "pre";
    }

    /**
     * 过滤的顺序 优先级为0，数字越大，优先级越低
     *
     * @return
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 这里可以写逻辑判断，是否要过滤，本文true,永远过滤
     *
     * @return
     */
    @Override
    public boolean shouldFilter() {
        boolean truth = checkNoLogin();
        logger.debug("!checkNoLogin():"+(!truth));
        return !truth;
    }

    /**
     * 过滤器的具体逻辑。可用很复杂，包括查sql，nosql去判断该请求到底有没有权限访问。
     *
     * @return
     */
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        HttpServletResponse response = ctx.getResponse();
        InputStream in = null;
        String token = "";
        try{
            logger.debug("??????????????????????1?"+request.getContentType()+"--"+(request.getContentType().contains("application/json")));
            if(request.getContentType().contains("application/json")){
                in = (InputStream) ctx.get("requestEntity");
                if (in == null) {
                    in = request.getInputStream();
                }
                //获取参数信息
                String body = StreamUtils.copyToString(in, Charset.forName("UTF-8"));
                logger.debug("body:"+body);
                JSONObject json = JSONObject.fromObject(body);
                token = StringUtils.trim(json.getString("token"));
                if(StringUtils.isBlank(token)){
                    ctx.setSendZuulResponse(false);
                    ctx.setResponseStatusCode(510);
                    response.setContentType("application/json;charset=utf-8");
                    response.setCharacterEncoding("utf-8");
                    ctx.setResponseBody("您可能登录已失效或未登录，请重新登录");
                    ctx.set("isSuccess", false);
                    return null;
                }

                String tokenStr = redisUtil.getValue(token,String.class);
                logger.debug("tokenStr:"+tokenStr);
                if(StringUtils.isBlank(tokenStr)){
                    ctx.setSendZuulResponse(false);
                    ctx.setResponseStatusCode(510);
                    response.setContentType("application/json;charset=utf-8");
                    response.setCharacterEncoding("utf-8");
                    ctx.setResponseBody("您可能登录已失效或未登录，请重新登录");
                    ctx.set("isSuccess", false);
                    return null;
                }
                JSONObject jsonToken = JSONObject.fromObject(tokenStr);



                //权限链接
                if(jsonToken.containsKey("menuUrlList")){
                    JSONArray jsonArray = jsonToken.getJSONArray("menuUrlList");
                    if(!checkPower(jsonArray,request.getRequestURI())){
                        ctx.setSendZuulResponse(false);
                        ctx.setResponseStatusCode(511);
                        response.setContentType("application/json;charset=utf-8");
                        response.setCharacterEncoding("utf-8");
                        ctx.setResponseBody("您未授权，请联系管理员填写访问权限。");
                        ctx.set("isSuccess", false);
                        return null;
                    }
                }
                logger.debug("jsonToken:"+jsonToken);
                String oper_id = jsonToken.getString("id");
                json.put("oper_id",oper_id);
                json.put("token",token);

                redisUtil.setKey(token,tokenStr,Long.valueOf(common.getSystem("LOGIN.OUT.TIME")), TimeUnit.MINUTES);

                final byte[] reqBodyBytes = json.toString().getBytes("UTF-8");
                ctx.setRequest(new HttpServletRequestWrapper(request) {
                    @Override
                    public ServletInputStream getInputStream() throws IOException {
                        return new ServletInputStreamWrapper(reqBodyBytes);
                    }
                    @Override
                    public int getContentLength() {
                        return reqBodyBytes.length;
                    }

                    @Override
                    public long getContentLengthLong() {
                        return reqBodyBytes.length;
                    }
                });
            }
            ctx.setSendZuulResponse(true); //对请求进行路由
            ctx.setResponseStatusCode(200);
            ctx.set("isSuccess", true);//打上标志位
            return null;
        }catch (Exception e){
            logger.error("出现错误",e);
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(200);
            response.setContentType("application/json;charset=utf-8");
            response.setCharacterEncoding("utf-8");
            returnMap.setMsgMaps("系统出现未知错误，请稍后再试");
            ctx.setResponseBody(new Gson().toJson(returnMap.getErrorReturnMap().getReturnMap()));
            ctx.set("isSuccess", false);
            return null;
        }

    }

    /**
     * 判断是否有访问权限
     * @param jsonArray
     * @param url
     * @return
     */
    public boolean checkPower(JSONArray jsonArray,String url){
        logger.debug("jsonArray:"+jsonArray);
        if(jsonArray != null){
            if(!jsonArray.isEmpty()){
                int cnt = jsonArray.size();
                for(int i=0;i<cnt;i++){
                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                    if(url.contains(jsonObject.getString("url"))){
                        return true;
                    }
                }
            }
        }
        return false;
    }

}
